package org.etnaframework.module.web.api;

import org.etnaframework.module.web.api.WebCommonFilter.ContentCachingRequestWrapperPlus;
import org.springframework.http.HttpStatus;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Web服务器通用配置
 *
 * @author jasyaf
 * @since 2023-12-27
 */
public interface IWebCommonCustomizer {

    /**
     * 获取请求来源IP的方法，可以根据是否有前置代理、有几层代理来定制
     * <p>
     * 注意：由于使用了{@link WebCommonFilter}，在业务代码中调用{@link HttpServletRequest#getRemoteAddr()}时
     * 实际上调用的是{@link ContentCachingRequestWrapperPlus#getRemoteAddr()}，在方法体内调用的就是本方法
     * <p>
     * 所以在业务代码中获取来源IP，调用{@link HttpServletRequest#getRemoteAddr()}即可，不要直接通过本方法来获取，这样会导致运行效率降低！！
     */
    String getRemoteAddr(HttpServletRequest request);

    /**
     * 获取请求来源scheme(http/https)，根据前置代理情况定制
     * <p>
     * 注意：由于使用了{@link WebCommonFilter}，在业务代码中调用{@link HttpServletRequest#getScheme()}时
     * 实际上调用的是{@link ContentCachingRequestWrapperPlus#getScheme()}，在方法体内调用的就是本方法
     * <p>
     * 所以在业务代码中获取来源IP，调用{@link HttpServletRequest#getScheme()}即可，不要直接通过本方法来获取，这样会导致运行效率降低！！
     */
    String getScheme(HttpServletRequest request);

    /**
     * 在进入业务代码前执行的程序，可以在这里放一些全局的资源初始化操作，例如放置链路追踪ID
     */
    void beforeRequest(HttpServletRequest request, HttpServletResponse response);

    /**
     * 业务代码执行完毕后执行的程序（出错中止后也会执行），可以在这里放一些资源回收的操作，例如回收链路追踪ID
     */
    void afterRequest(HttpServletRequest request, HttpServletResponse response);

    /**
     * 错误页的处理，可以在这里自定义404/500的显示规则，如果是纯API服务器也可以返回特定的JSON字符串
     * 注意：如果在{@link #error(HttpServletRequest, HttpServletResponse, Throwable)}中再抛出异常，也会进入到这里作为最后的兜底
     */
    void errorPage(HttpServletRequest request, HttpServletResponse response, HttpStatus status);

    /**
     * Web请求处理过程中抛出的异常处理，可自定义哪些异常返回什么数据给前端，也可以针对异常类型添加监控告警相关的代码
     */
    void error(HttpServletRequest request, HttpServletResponse response, Throwable ex);
}
